home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
276-300
/
299
/
rxil
/
demo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
13KB
|
589 lines
/* demo.c */
/* A small demo program for the Rxil library.
*
* This must be run from the CLI only. This is due to the diagnostic
* info that is sent to the CLI.
*
* This program implments a fairly full-featured ARexx port.
* The demo program itself is more along the lines of a "hack" and
* was not written with robustness in mind (especially the child macro
* launching stuff).
* It does show how few the lines of code needed are.
*/
/* Copyright © 1989 by Donald T. Meyer, Stormgate Software
* All Rights Reserved
*
* This source code may be compiled and used in any software
* product.
* No portion of this source code is to be re-distributed or
* sold for profit.
*
* Donald T. Meyer
* Stormgate Software
* P.O. Box 383
* St. Peters, MO 63376
*
* BIX: donmeyer (usually daily)
* GEnie: D.MEYER (weekly)
* PLINK: Stormgate (weekly)
*/
/* The Commands this program understands from ARexx:
*
* STATUS <l|b|x|y|z>
* A do-nothing command which returns various strings and result
* codes.
*
* DUMP [e|c|s]
* Display some things about the ARexx environment that this
* program has established.
*
* LOCK
* Engage this program in an exclusive conversation.
* Returns the name of the secret port.
*
* UNLOCK
* Releases the lock.
*
* LCMD
* Allows the launching of an ARexx program as a "command".
*
* LFUNC
* Allows the launching of an ARexx program as a "function".
*
* PTEST
* Returns a dummy string. Works only from a "child" ARexx
* program or from an ARexx program which has acquired a lock.
*
* QUIT
* Causes the program to terminate. This is the only way to
* exit!
*
*
* These descriptions are terse, I know. Looking at the code here
* is the best way to get a feel for just what is happening.
* To play with this, run it, and then run an ARexx program whose
* host address is set to "MYREXX_TEST_#1".
* Then issue some commands! Note that most things require that the
* results flag be set via an ARexx "options results" statement.
*/
#include "rxil.h"
#include <graphics/gfxbase.h>
#include <libraries/dos.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef LATTICE
#include <proto/intuition.h>
#endif
/*--------------------------------------------------------------------*/
void openlibrarys( void );
void closelibrarys( void );
void cleanup( void );
void bailout( char *message, int rc );
void eventloop( void );
void cmd_status( struct RexxMsg *rexxmsg );
void cmd_quit( struct RexxMsg *rexxmsg );
void cmd_launch_cmd( struct RexxMsg *rexxmsg );
void cmd_launch_func( struct RexxMsg *rexxmsg );
void cmd_ptest( struct RexxMsg *rexxmsg );
void cmd_dump( struct RexxMsg *rexxmsg );
/*--------------------------------------------------------------------*/
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
BOOL finished = FALSE;
/************************************
* *
* Defined for Rexx Interface *
* *
************************************/
struct RxilDef *global_rdef = NULL;
struct RxilFunction rexx_cmd_table[] = {
{ "lock", &RxilCmdLock, 0, 0, FALSE, RXIL_PUBLIC },
{ "unlock", &RxilCmdUnlock, 0, 0, FALSE, RXIL_SECRET },
{ "status", &cmd_status, 1, 1, FALSE, RXIL_PUBLIC },
{ "quit", &cmd_quit, 0, 0, FALSE, RXIL_PUBLIC },
{ "dump", &cmd_dump, 0, 1, FALSE, RXIL_PUBLIC },
{ "lcmd", &cmd_launch_cmd, 0, 0, FALSE, RXIL_PUBLIC },
{ "lfunc", &cmd_launch_func, 0, 0, FALSE, RXIL_PUBLIC },
{ "ptest", &cmd_ptest, 0, 0, FALSE, RXIL_SECRET },
/* Mark end-of-table */
{ NULL, NULL, 0, 0, FALSE, 0 }
};
/********************************************************************/
struct RxilInvocation *rxi_func;
struct RxilInvocation *rxi_cmd;
/* For general purpose testing use. These would not be
* needed as other than local, temporary variables if we were
* allocating and de-allocating RxilInvocation structures on
* the fly (since the Rxil library tracks all RxilInvocation
* structures allocated).
*/
struct RxilInvocation *rxi_startup;
/* This one is for the startup macro. We want to retain it's pointer
* even after it is launched so that we can "recognize" it when
* it terminates and handle it differently.
*/
/*--------------------------------------------------------------------*/
void main( int argc, char *argv[] )
{
openlibrarys();
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* This will open the rexx library, and the desired ports.
* If all we want to do is receive commands, we probably
* would not open the secret port, although we might.
*/
global_rdef = RxilInit( RXIL_PUBLIC | RXIL_SECRET, "MYREXX_TEST" );
if( global_rdef == NULL )
{
bailout( "Unable to init rexx", 0 );
}
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* Init the members in the RxilDef structure which customize
* the way things work.
*/
/* global_rdef->Flags = RXIL_NO_REQ | RXIL_NO_ABORT; */
/* Set flags here to control various characteristics of the
* library routines.
* The default in this demo is to not set any flags, which
* typicaly turn _off_ features.
*/
global_rdef->Console = "CON:10/10/400/150/RexxCon";
/* All commands or functions launched by this program will open
* a console window of this specification. Set this to NULL to
* default to no window.
*/
global_rdef->Extension = "rexx";
/* this normally would be an application
* specific macro filename extension.
*/
global_rdef->HostPort = "REXX";
/* If this is AREXX, launches will default
* to async (as opposed to synchronous).
*/
global_rdef->CommandTable = &rexx_cmd_table[0];
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* Pre-allocate some invocation structures. These could
* also be allocated and de-allocated on-the-fly if desired.
* One possible philosophy would be to allocate one structure
* for each possible macro command. This would speed macro
* invocations by a slight amount.
*/
rxi_cmd = RxilCreateRxi( NULL, RXCOMM );
if( rxi_cmd == NULL )
{
bailout( "Unable to allocate command_rxi", RETURN_FAIL );
}
rxi_func = RxilCreateRxi( NULL, RXFUNC );
if( rxi_func == NULL )
{
bailout( "Unable to allocate function_rxi", RETURN_FAIL );
}
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* This is an example of running a "startup" macro each time the
* program is invoked. The RxilInvocation will be allocated and
* then freed when it returns.
*/
rxi_startup = RxilCreateRxi( "startup.rxil", RXCOMM );
if( rxi_startup == NULL )
{
/* Just because the startup macro did not work, you would
* probably not normally give up.
*/
printf( "** Unable to allocate startup rxi **\n" );
}
else
{
/* We want our own console spec, not the default. In some
* (most?) real applications a console would probably not be
* opened. We do it here for illustration purposes.
*/
rxi_startup->Console = "CON:0/80/620/100/Demo Startup Macro";
if( RxilLaunch( rxi_startup ) != 0 )
{
/* Informative message only */
printf( "** Unable to launch the startup macro **\n" );
}
}
eventloop();
cleanup();
}
/*-----------------------------------------------------------------*/
void eventloop( void )
{
struct RxilInvocation *rxi;
ULONG flags;
while( !finished )
{
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* Note that we include the rexx port signal bit(s) in the wait().
*/
flags = Wait( RXIL_WAITFLAG );
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* Now do the ARexx port stuff.
*/
if( FlagIsSet( flags, RXIL_WAITFLAG ) )
{
RxilCheckPort();
}
/* Some info for debugging purposes... */
printf( "---Event---\n" );
printf( "rxi_cmd state: %d\n", (int)rxi_cmd->State );
printf( "rxi_func state: %d\n", (int)rxi_func->State );
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* Get any ARexx invocation returns which may be back.
* This code would not be present on a minimal implementation
* which does not launch macros, just responds to simple
* commands.
*/
while( ( rxi = RxilGetReturn() ) != NULL )
{
if( rxi->Type == RXCOMM )
{
printf( "Command Invocation completed\n" );
}
else
{
printf( "Function Invocation completed\n" );
}
if( rxi == rxi_startup )
{
/* This is our startup macro terminating. We handle
* this differently since we don't want to display
* an error if not found (which the standard routine
* RxilHandleReturn would do). And we also want to
* de-allocate the RxilInvocation structure.
*/
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+
* Deallocate things, close console windows, etc.
* Then free the structure.
*/
if( ( rxi->RexxMsg->rm_Result1 != RC_WARN ) ||
( rxi->RexxMsg->rm_Result2 != ERR10_001 ) )
{
/* The error is not just "program not found".
* This is a true error, tell the user.
*/
RxilHandleReturn( rxi );
}
RxilCleanupReturn( rxi );
RxilDeleteRxi( rxi );
rxi_startup = NULL; /* To be tidy... */
}
else
{
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+
* Tell user about error returns, etc.
* This can either be replaced by client code to handle
* returns in a specific way, or not done at all (not very
* friendly) and nothing will break...
*/
RxilHandleReturn( rxi );
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+
* Deallocate things, close console windows, etc.
*/
RxilCleanupReturn( rxi );
}
}
}
}
void cmd_status( struct RexxMsg *rexxmsg )
{
printf( "Cmd status\n" );
printf( "The FromRexx variable is %d\n", RXIL_FROM_REXX );
switch( *RXIL_ARGV(1) )
{
case 'L':
case 'l':
RxilSetResult( rexxmsg, "Hi there!" );
break;
case 'B':
case 'b':
RxilSetResult( rexxmsg, "I'm NOT Fine!" );
break;
case 'X':
case 'x':
rexxmsg->rm_Result1 = 20;
break;
case 'Y':
case 'y':
rexxmsg->rm_Result1 = 100;
break;
case 'Z':
case 'z':
rexxmsg->rm_Result1 = 200;
break;
default:
rexxmsg->rm_Result1 = RXERR_INVALID_ARG;
}
}
/* This will only succeed if the command comes in at the private port.
*/
void cmd_ptest( struct RexxMsg *rexxmsg )
{
printf( "Cmd privilege test\n" );
RxilSetResult( rexxmsg, "You are privileged indeed!" );
}
/* Cause the demo program to exit. */
void cmd_quit( struct RexxMsg *rexxmsg )
{
printf( "Cmd quit\n" );
finished = TRUE;
}
void cmd_dump( struct RexxMsg *rexxmsg )
{
ULONG flags = 0;
if( RXIL_ARGC > 1 )
{
if( strnicmp( RXIL_ARGV(1), "ENVIRONMENT",
strlen(RXIL_ARGV(1)) ) == 0 )
{
flags = RXIL_DUMP_ENV;
}
if( strnicmp( RXIL_ARGV(1), "STATE",
strlen(RXIL_ARGV(1)) ) == 0 )
{
flags = RXIL_DUMP_STATE;
}
if( strnicmp( RXIL_ARGV(1), "COMMANDS",
strlen(RXIL_ARGV(1)) ) == 0 )
{
flags = RXIL_DUMP_CMDS;
}
}
else
{
flags = RXIL_DUMP_ENV | RXIL_DUMP_CMDS | RXIL_DUMP_STATE;
}
if( flags == 0 )
{
/* The keyword was not valid */
rexxmsg->rm_Result1 = RXERR_INVALID_ARG;
return;
}
RxilDumpRdef( global_rdef, flags );
}
void cmd_launch_cmd( struct RexxMsg *rexxmsg )
{
static char buf[100];
LONG rc;
printf( "Cmd launch command:" );
gets( buf );
rxi_cmd->Name = buf;
rc = RxilLaunch( rxi_cmd );
printf( "Launch returned %d\n", rc );
}
static char buf[16][100];
void cmd_launch_func( struct RexxMsg *rexxmsg )
{
LONG rc;
int i;
printf( "Cmd launch function:" );
gets( &buf[0][0] );
for( i=1; i<16; i++ )
{
printf( "Enter arg %d: ", i );
gets( &buf[i][0] );
if( strlen(&buf[i][0]) > 0 )
{
rxi_func->FuncArg[i] = &buf[i][0];
}
else
{
rxi_func->FuncArg[i] = NULL;
break;
}
}
rxi_func->Name = &buf[0][0];
rc = RxilLaunch( rxi_func );
printf( "Launch returned %d\n", rc );
}
/*-----------------------------------------------------------------*/
void openlibrarys( void )
{
/* Intuition */
if( ! ( IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 33 ) ) )
{
bailout( "Unable to open the Intuition Library", RETURN_FAIL );
}
/* Graphics */
if( ! ( GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", 33 ) ) )
{
bailout("Unable to open the Graphics Library", RETURN_FAIL );
}
}
void closelibrarys( void )
{
if( IntuitionBase ) CloseLibrary( (struct Library *)IntuitionBase );
if( GfxBase ) CloseLibrary( (struct Library *)GfxBase );
}
void cleanup( void )
{
/* =+=+=+=+=+=+=+=+=+ ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
* This will handle ALL the cleanup details. If we wished to make
* sure that there were no macro program invocations running before
* we call this routine (and it waits, which may distress the user)
* we should test our ability to terminate by calling RxilPending().
*/
RxilCleanup( global_rdef );
global_rdef = NULL;
closelibrarys();
}
void bailout( char *message, int rc )
{
printf( "%s/n", message );
cleanup();
exit( rc );
}